"""
This file contains various tests used during the generation of 
exceptional fillings on the 10-tetrahedra census

The method 
    get_short_slopes(m_name, length = 6, verified = True, bits_prec = 10000)
generates the slopes no longer than the given length associated to the given manifold,
which we used to generate the candidates of exceptional fillings.

The rest of the code are the tests, which generally follow the following format:

INPUT: m_name, the string of the name of a 1-cusped manifold or the filled manifold (e.g. o10_000001(1, 0))
OUTPUT: the result of the test, which is 
    the string of combinatorial name for filled_to_regina_name(),
    and True or False for other tests.

Some tests have extra parameters as input, see the comments in the code of the tests.

The codes used for combinatorial recognition are essentially part of those in the paper 

    A Census of Exceptional Fillings
        by N. Dunfield, Characters in low-dimensional topology, Contemp. Math. 760 (2020) 143-155,

with slight changes such as minor bug fixes and adaption to up-to-date SnapPy and Regina.
"""

from util import *

def get_short_slopes(m_name, length = 6, verified = True, bits_prec = 10000):
    m = snappy.Manifold(m_name)
    try:
        return m.short_slopes(length = length, verified = verified, bits_prec = bits_prec)
    except:
        m.randomize()
        return get_short_slopes(m, length, verified, bits_prec)


def closed_certify_hyperbolicity(m_name, trys = 200, max_tets = 50, bits_prec = 202):
    """
    For some closed manifolds, it is necessary to put:
        trys = 10000
        bits_prec = 5000
    in order to obtain an affirmative answer.
    """
    sigs_list = closed_isosigs(m_name, trys=trys, max_tets= max_tets)

    for sig in sigs_list:
        m = snappy.ManifoldHP(sig)
        for i in range(trys):
            try:
                if m.verify_hyperbolicity(bits_prec = bits_prec)[0]: 
                    return True
            except:
                continue
            m.randomize()

    return False

def filled_to_regina_name(m_name, trys = 1000):
    return regina_name(m_name,trys=trys)

def detect_essential_surface(closed_snappy_manifold, trys= 40):
    # is_toroidal with minor changes to also check the existence of essential spheres.
    
    isosigs = closed_isosigs(closed_snappy_manifold, trys=trys, max_tets=40)
    if len(isosigs) == 0:
        return
    T = to_regina(isosigs[0])
    #assert T.isZeroEfficient()
    surfaces = regina.NormalSurfaces(T,
                          regina.NS_STANDARD, regina.NS_FUNDAMENTAL)
    for S in surfaces:
        if S.eulerChar() >= 0:
            if not S.isOrientable():
                S = S.doubleSurface()
            assert S.isOrientable()
            X = S.cutAlong()
            X.intelligentSimplify()
            pieces = X.triangulateComponents()
            if (S.eulerChar() == 0 and all(not C.hasCompressingDisc() for C in pieces)) or ((S.eulerChar()>0) and all(not C.isBall() for C in pieces)):
                return True
    return False